import {
  Controller,
  Get,
  Post,
  Body,
  Param,
  Delete,
  Put,
  Query,
  UseGuards,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiParam,
  ApiQuery,
  ApiBearerAuth,
} from '@nestjs/swagger';
import { TaskCategoriesService } from './task-categories.service';
import { CreateTaskCategoryDto } from './dto/create-task-category.dto';
import { UpdateTaskCategoryDto } from './dto/update-task-category.dto';
import { TaskCategoryDto } from './dto/task-category.dto';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles } from '../auth/decorators/roles.decorator';
import { UserRole } from '../common/enums';
import { UuidValidationPipe } from '../common/pipes/uuid-validation.pipe';

@ApiTags('Task Category')
@Controller('task-categories')
@UseGuards(JwtAuthGuard, RolesGuard)
@ApiBearerAuth()
export class TaskCategoriesController {
  constructor(private readonly taskCategoriesService: TaskCategoriesService) {}

  @Post()
  @Roles(UserRole.ADMIN)
  @ApiOperation({ summary: 'Create a new task category' })
  @ApiResponse({
    status: 201,
    description: 'The task category has been successfully created.',
    type: TaskCategoryDto,
  })
  create(@Body() createTaskCategoryDto: CreateTaskCategoryDto): Promise<TaskCategoryDto> {
    return this.taskCategoriesService.create(createTaskCategoryDto);
  }

  @Get()
  @ApiOperation({ summary: 'Get all task categories' })
  @ApiQuery({ name: 'page', required: false, type: Number, description: 'Page number' })
  @ApiQuery({ name: 'pageSize', required: false, type: Number, description: 'Page size' })
  @ApiResponse({
    status: 200,
    description: 'Return all task categories',
    schema: {
      type: 'object',
      properties: {
        data: {
          type: 'array',
          items: { $ref: '#/components/schemas/TaskCategoryDto' },
        },
        pagination: {
          type: 'object',
          properties: {
            total: { type: 'number' },
            page: { type: 'number' },
            pageSize: { type: 'number' },
          },
        },
      },
    },
  })
  async findAll(
    @Query('page') page = 1,
    @Query('pageSize') pageSize = 20,
  ): Promise<{
    data: TaskCategoryDto[];
    pagination: { total: number; page: number; pageSize: number };
  }> {
    const { data, total } = await this.taskCategoriesService.findAll(+page, +pageSize);
    return {
      data,
      pagination: {
        total,
        page: +page,
        pageSize: +pageSize,
      },
    };
  }

  @Get(':categoryId')
  @ApiOperation({ summary: 'Get a task category by ID' })
  @ApiParam({ name: 'categoryId', description: 'The ID of the task category' })
  @ApiResponse({
    status: 200,
    description: 'Return the task category',
    type: TaskCategoryDto,
  })
  @ApiResponse({ status: 404, description: 'Task category not found' })
  @ApiResponse({ status: 400, description: 'Invalid UUID format' })
  findOne(@Param('categoryId', UuidValidationPipe) id: string): Promise<TaskCategoryDto> {
    return this.taskCategoriesService.findOne(id);
  }

  @Put(':categoryId')
  @Roles(UserRole.ADMIN)
  @ApiOperation({ summary: 'Update a task category' })
  @ApiParam({ name: 'categoryId', description: 'The ID of the task category' })
  @ApiResponse({
    status: 200,
    description: 'The task category has been successfully updated.',
    type: TaskCategoryDto,
  })
  @ApiResponse({ status: 404, description: 'Task category not found' })
  @ApiResponse({ status: 400, description: 'Invalid UUID format' })
  update(
    @Param('categoryId', UuidValidationPipe) id: string,
    @Body() updateTaskCategoryDto: UpdateTaskCategoryDto,
  ): Promise<TaskCategoryDto> {
    return this.taskCategoriesService.update(id, updateTaskCategoryDto);
  }

  @Delete(':categoryId')
  @Roles(UserRole.ADMIN)
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: 'Delete a task category' })
  @ApiParam({ name: 'categoryId', description: 'The ID of the task category' })
  @ApiResponse({ status: 204, description: 'The task category has been successfully deleted' })
  @ApiResponse({ status: 404, description: 'Task category not found' })
  @ApiResponse({ status: 400, description: 'Invalid UUID format' })
  @ApiResponse({
    status: 409,
    description: 'Cannot delete task category that is being used by active tasks',
  })
  remove(@Param('categoryId', UuidValidationPipe) id: string): Promise<void> {
    return this.taskCategoriesService.remove(id);
  }
}
